Practicum 1.2

Loading dataset

library(readr)

getwd()
[1] "C:/Users/fmojt/Documents/RProjects/R_practicals/practicum_1.2"
fifa_df = read_csv("players_22.csv")
Rows: 19239 Columns: 110── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (48): player_url, short_name, long_name, player_positions, club_name, league_name, club_position, club_loaned_from, nationality...
dbl  (60): sofifa_id, overall, potential, value_eur, wage_eur, age, height_cm, weight_kg, club_team_id, league_level, club_jersey_nu...
date  (2): dob, club_joined
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
View(fifa_df)

Reducing dataset

Here we reduce the dataset by filtering the columns we are going to need in this practicum.


library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
cols <- c("short_name", "league_name", "preferred_foot", "player_positions", "overall", "value_eur", "wage_eur", "dob", "potential")

fifa_df_reduced <- fifa_df %>%
  select(all_of(cols))

fifa_df_reduced

Distribution of left-footed players across all leagues

First step is to quickly examine the distribution of left-footed players in all leagues.

League-Player distribution


library(dplyr)

# fifa_df %>%
#   filter(preferred_foot == "Left") %>%
#   group_by(league_name) %>%
#   summarise(left_footed_pl_count = n()) %>%
#   print()

# faster alternative
fifa_df_reduced %>%
  filter(preferred_foot == 'Left') %>%
  count(league_name, name = 'left_footed_pl_count') 

Visualization

Based on the visualization below, we can see that average proportion of left-footed players across all leagues makes up approximately 25% of whole.

library(ggplot2)

fifa_df_reduced %>%
  count(league_name, preferred_foot) %>%
  ggplot(aes(x = league_name, y = n, fill = preferred_foot)) +
  geom_bar(stat = "identity", position = "fill") +  # "fill" makes it a proportion (stacked)
  labs(title = "Proportion of Left-Footed Players in Each League",
       x = "League",
       y = "Proportion") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

Proportion of player position categories

We utilize ggplot2 library to visualize proportions of left and right-footed players for each player_category.

Data bucketing

First, custom groupings of player positions need to be created. We are going to bucket the positions into offensive, defensive and midfielder bins. Final step of this process involves adding a new column storing these categories for each player.


# Define offensive and defensive positions
offensive_positions <- c("LF", "CF", "RF", "LW", "RW", "LS", "ST", "RS")
defensive_positions <- c("LWB", "RWB", "LCB", "CB", "RCB", "LB", "RB")
midfielder_positions <- c("LM", "LAM", "CM", "RM", "RAM", "CAM", "CDM", "DM", "LDM", "RDM")


# Categorize player positions
fifa_df_reduced <- fifa_df_reduced %>%
  mutate(position_category = case_when(
    player_positions %in% offensive_positions ~ "Offensive",
    player_positions %in% defensive_positions ~ "Defensive",
    player_positions %in% midfielder_positions ~ "Midfielder",
    TRUE ~ "Other"
  ))

fifa_df

Grouping the buckets

Second step involves grouping the buckets and calculating the count for each.


# Summarize data to get the count of players by position and preferred foot
grouping_counts <- fifa_df_left_right %>%
  group_by(position_category, preferred_foot) %>%
  summarise(Count = n()) %>%
  ungroup()
`summarise()` has grouped output by 'position_category'. You can override using the `.groups` argument.
grouping_counts
NA

Plotting

By following the principles of functional programming, we are going to define a function which will visualize a distribution plot for any column we may need.


library(tidyverse)

plot_metric <- function(df, target, count, fill, title, subtitle) {
  p <- df %>%
    ggplot(aes(x = reorder(.data[[target]], .data[[count]]), y = .data[[count]], fill = .data[[fill]])) +
    geom_col() + 
    geom_text(aes(label = .data[[count]]), 
              colour = "white", position = position_stack(vjust = 0.5)) + 
    scale_fill_manual(values=c('#3153a2', 'lightgrey')) + 
    coord_flip() +
    labs(title = title, 
         subtitle = subtitle,
         fill = fill) +
    theme(legend.position = "bottom", 
          axis.title.y = element_blank(),
          axis.title.x = element_blank(),
          # panel.border = element_blank(),
          # axis.line = element_line(colour = "grey"),
          # axis.ticks = element_line(color = "grey"),
          # axis.text.y = element_text(size = 11),
          # plot.subtitle = element_text(size = 9)) + 
    ) +
    guides(fill = guide_legend(title = fill))
  
  return(p)
}

plot_metric(position_summary, "position_category", "Count",
            "preferred_foot",
            "Comparison of Player Positions by Preferred Foot", 
            "Counts of Player Positions of left- and right-footed players")

NA
NA

Comparison of Market Value and Vague

In this section we are about to analyze whether left-footed players have generally higher Market Value and Vague than their right-footed counterparts. We are going to achieve this by visualizing the mean of both attributes for left- and right-footed player.

Data Preprocessing

First step involves adding new columns containing the average of Wage and Market Value. In order to achieve that, we need to group the dataset by the preferred_foot and calculating the mean of each option.

library(dplyr)

# Summarize data: average value and wage for each foot preference
modified_df <- fifa_df_reduced %>%
  group_by(preferred_foot) %>%
  summarise(AVG_VALUE_EUR = mean(value_eur, na.rm = TRUE),
            AVG_WAGE_EUR = mean(wage_eur, na.rm = TRUE)) %>%
  ungroup()

modified_df
library(tidyverse)


# Plot for AVG_VALUE_EUR
plot_metric(modified_df, "preferred_foot", "AVG_VALUE_EUR", "preferred_foot",
            "Comparison of Market Value by Preferred Foot",
            "Average market value (EUR) of left- and right-footed players")


# Plot for AVG_VALUE_EUR
plot_metric(modified_df, "preferred_foot", "AVG_WAGE_EUR", "preferred_foot",
            "Comparison of Market Value by Preferred Foot",
            "Average market value (EUR) of left- and right-footed players")

NA
NA

Comparison of young players’ potential

We also compare whether young left-footed players have greater average potential than the right-footed.

Data preprocessing

Only players born in 2004 are considered young. Therefore we reduce the dataset as follows.


library(dplyr)

# Summarize average potential for left-footed players
left_footed_avg <- fifa_df_reduced %>%
  filter(preferred_foot == 'Left' & format(dob, "%Y") == "2004") %>%
  summarise(players = 'Left-footed', avg = mean(potential, na.rm = TRUE))

# Summarize average potential for right-footed players
right_footed_avg <- fifa_df_reduced %>%
  filter(preferred_foot == 'Right' & format(dob, "%Y") == "2004") %>%
  summarise(players = 'Right-footed', avg = mean(potential, na.rm = TRUE))

# Combine both summaries
avg_potential_df <- bind_rows(left_footed_avg, right_footed_avg)
avg_potential_df
  # select(short_name, dob, potential, everything())

Plotting

Finally, we visualize the means in a simple bar plot below.

library(ggplot2)
# Create a bar plot comparing the average potential for left and right-footed players
ggplot(avg_potential_df, aes(x = players, y = avg, fill = players)) +
  geom_bar(stat = "identity") +
  labs(title = "Comparison of Average Potential of Left- and Right-Footed Players",
       x = "Footedness",
  
       y = "Average Potential") +
  scale_fill_manual(values = c('#3153a2', "lightgrey")) +
  theme_minimal() +
  theme(legend.position = "none")

Conclusion

We hypothesized that left-footed players generally play in more offensive positions that the right-footed players. As of the observation we performed in this document we can reject this hypothesis since the greatest proportion of left-footed players are playing in defensive positions.

We also hypothesized that left-footed players have greater market value and wage on average than the right-footed players. Based on the analysis, we can declare this claim as correct but it remains questionable to what extent.

Finally we set another hypothesis which says that young left-footed players have greater potential. After reviewing the average we can proclaim this final hypothesis as true if the observed difference is significant.

Hypothesis testing

First hypothesis can be tested via Chi-square test for independence. The rest of the hypotheses may be tested by a simple independent Two-sample T-test (Student’s T-test) since we are comparing the means of independent groups.

library(dplyr)

fifa_df_clean <- fifa_df_reduced %>%
  filter(!is.na(preferred_foot) & !is.na(position_category))

chisq.test(table(fifa_df_clean$preferred_foot, fifa_df_clean$position_category))

    Pearson's Chi-squared test

data:  table(fifa_df_clean$preferred_foot, fifa_df_clean$position_category)
X-squared = 196.21, df = 3, p-value < 2.2e-16
t.test(value_eur ~ preferred_foot, data = fifa_df_clean)

    Welch Two Sample t-test

data:  value_eur by preferred_foot
t = 2.7154, df = 7347.1, p-value = 0.006636
alternative hypothesis: true difference in means between group Left and group Right is not equal to 0
95 percent confidence interval:
  99667.84 617166.95
sample estimates:
 mean in group Left mean in group Right 
            3123795             2765378 
t.test(wage_eur ~ preferred_foot, data = fifa_df_clean)

    Welch Two Sample t-test

data:  wage_eur by preferred_foot
t = 2.2921, df = 7476.7, p-value = 0.02193
alternative hypothesis: true difference in means between group Left and group Right is not equal to 0
95 percent confidence interval:
  110.7626 1419.4680
sample estimates:
 mean in group Left mean in group Right 
           9601.461            8836.345 
t.test(potential ~ preferred_foot, data = fifa_df_clean)

    Welch Two Sample t-test

data:  potential by preferred_foot
t = 6.0452, df = 7797, p-value = 1.561e-09
alternative hypothesis: true difference in means between group Left and group Right is not equal to 0
95 percent confidence interval:
 0.4148673 0.8130385
sample estimates:
 mean in group Left mean in group Right 
           71.54765            70.93369 
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIFByYWN0aWN1bSAxLjINCg0KIyMjIExvYWRpbmcgZGF0YXNldA0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQoNCmdldHdkKCkNCg0KZmlmYV9kZiA9IHJlYWRfY3N2KCJwbGF5ZXJzXzIyLmNzdiIpDQpWaWV3KGZpZmFfZGYpDQoNCmBgYA0KDQojIyMgUmVkdWNpbmcgZGF0YXNldA0KDQpIZXJlIHdlIHJlZHVjZSB0aGUgZGF0YXNldCBieSBmaWx0ZXJpbmcgdGhlIGNvbHVtbnMgd2UgYXJlIGdvaW5nIHRvIG5lZWQgaW4gdGhpcyBwcmFjdGljdW0uDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KGRwbHlyKQ0KDQpjb2xzIDwtIGMoInNob3J0X25hbWUiLCAibGVhZ3VlX25hbWUiLCAicHJlZmVycmVkX2Zvb3QiLCAicGxheWVyX3Bvc2l0aW9ucyIsICJvdmVyYWxsIiwgInZhbHVlX2V1ciIsICJ3YWdlX2V1ciIsICJkb2IiLCAicG90ZW50aWFsIikNCg0KZmlmYV9kZl9yZWR1Y2VkIDwtIGZpZmFfZGYgJT4lDQogIHNlbGVjdChhbGxfb2YoY29scykpDQoNCmZpZmFfZGZfcmVkdWNlZA0KYGBgDQoNCiMjIERpc3RyaWJ1dGlvbiBvZiBsZWZ0LWZvb3RlZCBwbGF5ZXJzIGFjcm9zcyBhbGwgbGVhZ3Vlcw0KDQpGaXJzdCBzdGVwIGlzIHRvIHF1aWNrbHkgZXhhbWluZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGxlZnQtZm9vdGVkIHBsYXllcnMgaW4gYWxsIGxlYWd1ZXMuDQoNCiMjIyBMZWFndWUtUGxheWVyIGRpc3RyaWJ1dGlvbg0KDQpgYGB7cn0NCg0KbGlicmFyeShkcGx5cikNCg0KIyBmaWZhX2RmICU+JQ0KIyAgIGZpbHRlcihwcmVmZXJyZWRfZm9vdCA9PSAiTGVmdCIpICU+JQ0KIyAgIGdyb3VwX2J5KGxlYWd1ZV9uYW1lKSAlPiUNCiMgICBzdW1tYXJpc2UobGVmdF9mb290ZWRfcGxfY291bnQgPSBuKCkpICU+JQ0KIyAgIHByaW50KCkNCg0KIyBmYXN0ZXIgYWx0ZXJuYXRpdmUNCmZpZmFfZGZfcmVkdWNlZCAlPiUNCiAgZmlsdGVyKHByZWZlcnJlZF9mb290ID09ICdMZWZ0JykgJT4lDQogIGNvdW50KGxlYWd1ZV9uYW1lLCBuYW1lID0gJ2xlZnRfZm9vdGVkX3BsX2NvdW50JykgDQpgYGANCg0KIyMjIFZpc3VhbGl6YXRpb24NCg0KQmFzZWQgb24gdGhlIHZpc3VhbGl6YXRpb24gYmVsb3csIHdlIGNhbiBzZWUgdGhhdCBhdmVyYWdlIHByb3BvcnRpb24gb2YgbGVmdC1mb290ZWQgcGxheWVycyBhY3Jvc3MgYWxsIGxlYWd1ZXMgbWFrZXMgdXAgYXBwcm94aW1hdGVseSAyNSUgb2Ygd2hvbGUuDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQpmaWZhX2RmX3JlZHVjZWQgJT4lDQogIGNvdW50KGxlYWd1ZV9uYW1lLCBwcmVmZXJyZWRfZm9vdCkgJT4lDQogIGdncGxvdChhZXMoeCA9IGxlYWd1ZV9uYW1lLCB5ID0gbiwgZmlsbCA9IHByZWZlcnJlZF9mb290KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZmlsbCIpICsgICMgImZpbGwiIG1ha2VzIGl0IGEgcHJvcG9ydGlvbiAoc3RhY2tlZCkNCiAgbGFicyh0aXRsZSA9ICJQcm9wb3J0aW9uIG9mIExlZnQtRm9vdGVkIFBsYXllcnMgaW4gRWFjaCBMZWFndWUiLA0KICAgICAgIHggPSAiTGVhZ3VlIiwNCiAgICAgICB5ID0gIlByb3BvcnRpb24iKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpDQpgYGANCg0KIyMgUHJvcG9ydGlvbiBvZiBwbGF5ZXIgcG9zaXRpb24gY2F0ZWdvcmllcw0KDQpXZSB1dGlsaXplIGdncGxvdDIgbGlicmFyeSB0byB2aXN1YWxpemUgcHJvcG9ydGlvbnMgb2YgbGVmdCBhbmQgcmlnaHQtZm9vdGVkIHBsYXllcnMgZm9yIGVhY2ggcGxheWVyX2NhdGVnb3J5Lg0KDQojIyMgRGF0YSBidWNrZXRpbmcNCg0KRmlyc3QsIGN1c3RvbSBncm91cGluZ3Mgb2YgcGxheWVyIHBvc2l0aW9ucyBuZWVkIHRvIGJlIGNyZWF0ZWQuIFdlIGFyZSBnb2luZyB0byBidWNrZXQgdGhlIHBvc2l0aW9ucyBpbnRvIG9mZmVuc2l2ZSwgZGVmZW5zaXZlIGFuZCBtaWRmaWVsZGVyIGJpbnMuIEZpbmFsIHN0ZXAgb2YgdGhpcyBwcm9jZXNzIGludm9sdmVzIGFkZGluZyBhIG5ldyBjb2x1bW4gc3RvcmluZyB0aGVzZSBjYXRlZ29yaWVzIGZvciBlYWNoIHBsYXllci4NCg0KYGBge3J9DQoNCiMgRGVmaW5lIG9mZmVuc2l2ZSBhbmQgZGVmZW5zaXZlIHBvc2l0aW9ucw0Kb2ZmZW5zaXZlX3Bvc2l0aW9ucyA8LSBjKCJMRiIsICJDRiIsICJSRiIsICJMVyIsICJSVyIsICJMUyIsICJTVCIsICJSUyIpDQpkZWZlbnNpdmVfcG9zaXRpb25zIDwtIGMoIkxXQiIsICJSV0IiLCAiTENCIiwgIkNCIiwgIlJDQiIsICJMQiIsICJSQiIpDQptaWRmaWVsZGVyX3Bvc2l0aW9ucyA8LSBjKCJMTSIsICJMQU0iLCAiQ00iLCAiUk0iLCAiUkFNIiwgIkNBTSIsICJDRE0iLCAiRE0iLCAiTERNIiwgIlJETSIpDQoNCg0KIyBDYXRlZ29yaXplIHBsYXllciBwb3NpdGlvbnMNCmZpZmFfZGZfcmVkdWNlZCA8LSBmaWZhX2RmX3JlZHVjZWQgJT4lDQogIG11dGF0ZShwb3NpdGlvbl9jYXRlZ29yeSA9IGNhc2Vfd2hlbigNCiAgICBwbGF5ZXJfcG9zaXRpb25zICVpbiUgb2ZmZW5zaXZlX3Bvc2l0aW9ucyB+ICJPZmZlbnNpdmUiLA0KICAgIHBsYXllcl9wb3NpdGlvbnMgJWluJSBkZWZlbnNpdmVfcG9zaXRpb25zIH4gIkRlZmVuc2l2ZSIsDQogICAgcGxheWVyX3Bvc2l0aW9ucyAlaW4lIG1pZGZpZWxkZXJfcG9zaXRpb25zIH4gIk1pZGZpZWxkZXIiLA0KICAgIFRSVUUgfiAiT3RoZXIiDQogICkpDQoNCmZpZmFfZGYNCmBgYA0KDQojIyMgR3JvdXBpbmcgdGhlIGJ1Y2tldHMNCg0KU2Vjb25kIHN0ZXAgaW52b2x2ZXMgZ3JvdXBpbmcgdGhlIGJ1Y2tldHMgYW5kIGNhbGN1bGF0aW5nIHRoZSBjb3VudCBmb3IgZWFjaC4NCg0KYGBge3J9DQoNCiMgU3VtbWFyaXplIGRhdGEgdG8gZ2V0IHRoZSBjb3VudCBvZiBwbGF5ZXJzIGJ5IHBvc2l0aW9uIGFuZCBwcmVmZXJyZWQgZm9vdA0KZ3JvdXBpbmdfY291bnRzIDwtIGZpZmFfZGZfbGVmdF9yaWdodCAlPiUNCiAgZ3JvdXBfYnkocG9zaXRpb25fY2F0ZWdvcnksIHByZWZlcnJlZF9mb290KSAlPiUNCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKSAlPiUNCiAgdW5ncm91cCgpDQoNCmdyb3VwaW5nX2NvdW50cw0KDQpgYGANCg0KIyMjIFBsb3R0aW5nDQoNCkJ5IGZvbGxvd2luZyB0aGUgcHJpbmNpcGxlcyBvZiBmdW5jdGlvbmFsIHByb2dyYW1taW5nLCB3ZSBhcmUgZ29pbmcgdG8gZGVmaW5lIGEgZnVuY3Rpb24gd2hpY2ggd2lsbCB2aXN1YWxpemUgYSBkaXN0cmlidXRpb24gcGxvdCBmb3IgYW55IGNvbHVtbiB3ZSBtYXkgbmVlZC4NCg0KYGBge3J9DQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQpwbG90X21ldHJpYyA8LSBmdW5jdGlvbihkZiwgdGFyZ2V0LCBjb3VudCwgZmlsbCwgdGl0bGUsIHN1YnRpdGxlKSB7DQogIHAgPC0gZGYgJT4lDQogICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlciguZGF0YVtbdGFyZ2V0XV0sIC5kYXRhW1tjb3VudF1dKSwgeSA9IC5kYXRhW1tjb3VudF1dLCBmaWxsID0gLmRhdGFbW2ZpbGxdXSkpICsNCiAgICBnZW9tX2NvbCgpICsgDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IC5kYXRhW1tjb3VudF1dKSwgDQogICAgICAgICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpKSArIA0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCcjMzE1M2EyJywgJ2xpZ2h0Z3JleScpKSArIA0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicyh0aXRsZSA9IHRpdGxlLCANCiAgICAgICAgIHN1YnRpdGxlID0gc3VidGl0bGUsDQogICAgICAgICBmaWxsID0gZmlsbCkgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCANCiAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICMgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICMgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5IiksDQogICAgICAgICAgIyBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyZXkiKSwNCiAgICAgICAgICAjIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksDQogICAgICAgICAgIyBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSkgKyANCiAgICApICsNCiAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9IGZpbGwpKQ0KICANCiAgcmV0dXJuKHApDQp9DQoNCnBsb3RfbWV0cmljKHBvc2l0aW9uX3N1bW1hcnksICJwb3NpdGlvbl9jYXRlZ29yeSIsICJDb3VudCIsDQogICAgICAgICAgICAicHJlZmVycmVkX2Zvb3QiLA0KICAgICAgICAgICAgIkNvbXBhcmlzb24gb2YgUGxheWVyIFBvc2l0aW9ucyBieSBQcmVmZXJyZWQgRm9vdCIsIA0KICAgICAgICAgICAgIkNvdW50cyBvZiBQbGF5ZXIgUG9zaXRpb25zIG9mIGxlZnQtIGFuZCByaWdodC1mb290ZWQgcGxheWVycyIpDQoNCg0KYGBgDQoNCiMjIENvbXBhcmlzb24gb2YgTWFya2V0IFZhbHVlIGFuZCBWYWd1ZQ0KDQpJbiB0aGlzIHNlY3Rpb24gd2UgYXJlIGFib3V0IHRvIGFuYWx5emUgd2hldGhlciBsZWZ0LWZvb3RlZCBwbGF5ZXJzIGhhdmUgZ2VuZXJhbGx5IGhpZ2hlciBNYXJrZXQgVmFsdWUgYW5kIFZhZ3VlIHRoYW4gdGhlaXIgcmlnaHQtZm9vdGVkIGNvdW50ZXJwYXJ0cy4gV2UgYXJlIGdvaW5nIHRvIGFjaGlldmUgdGhpcyBieSB2aXN1YWxpemluZyB0aGUgbWVhbiBvZiBib3RoIGF0dHJpYnV0ZXMgZm9yIGxlZnQtIGFuZCByaWdodC1mb290ZWQgcGxheWVyLg0KDQojIyMgRGF0YSBQcmVwcm9jZXNzaW5nDQoNCkZpcnN0IHN0ZXAgaW52b2x2ZXMgYWRkaW5nIG5ldyBjb2x1bW5zIGNvbnRhaW5pbmcgdGhlIGF2ZXJhZ2Ugb2YgV2FnZSBhbmQgTWFya2V0IFZhbHVlLiBJbiBvcmRlciB0byBhY2hpZXZlIHRoYXQsIHdlIG5lZWQgdG8gZ3JvdXAgdGhlIGRhdGFzZXQgYnkgdGhlIHByZWZlcnJlZF9mb290IGFuZCBjYWxjdWxhdGluZyB0aGUgbWVhbiBvZiBlYWNoIG9wdGlvbi4NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KDQojIFN1bW1hcml6ZSBkYXRhOiBhdmVyYWdlIHZhbHVlIGFuZCB3YWdlIGZvciBlYWNoIGZvb3QgcHJlZmVyZW5jZQ0KbW9kaWZpZWRfZGYgPC0gZmlmYV9kZl9yZWR1Y2VkICU+JQ0KICBncm91cF9ieShwcmVmZXJyZWRfZm9vdCkgJT4lDQogIHN1bW1hcmlzZShBVkdfVkFMVUVfRVVSID0gbWVhbih2YWx1ZV9ldXIsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBBVkdfV0FHRV9FVVIgPSBtZWFuKHdhZ2VfZXVyLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgdW5ncm91cCgpDQoNCm1vZGlmaWVkX2RmDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KDQojIFBsb3QgZm9yIEFWR19WQUxVRV9FVVINCnBsb3RfbWV0cmljKG1vZGlmaWVkX2RmLCAicHJlZmVycmVkX2Zvb3QiLCAiQVZHX1ZBTFVFX0VVUiIsICJwcmVmZXJyZWRfZm9vdCIsDQogICAgICAgICAgICAiQ29tcGFyaXNvbiBvZiBNYXJrZXQgVmFsdWUgYnkgUHJlZmVycmVkIEZvb3QiLA0KICAgICAgICAgICAgIkF2ZXJhZ2UgbWFya2V0IHZhbHVlIChFVVIpIG9mIGxlZnQtIGFuZCByaWdodC1mb290ZWQgcGxheWVycyIpDQoNCiMgUGxvdCBmb3IgQVZHX1ZBTFVFX0VVUg0KcGxvdF9tZXRyaWMobW9kaWZpZWRfZGYsICJwcmVmZXJyZWRfZm9vdCIsICJBVkdfV0FHRV9FVVIiLCAicHJlZmVycmVkX2Zvb3QiLA0KICAgICAgICAgICAgIkNvbXBhcmlzb24gb2YgTWFya2V0IFZhbHVlIGJ5IFByZWZlcnJlZCBGb290IiwNCiAgICAgICAgICAgICJBdmVyYWdlIG1hcmtldCB2YWx1ZSAoRVVSKSBvZiBsZWZ0LSBhbmQgcmlnaHQtZm9vdGVkIHBsYXllcnMiKQ0KDQoNCmBgYA0KDQojIyBDb21wYXJpc29uIG9mIHlvdW5nIHBsYXllcnMnIHBvdGVudGlhbA0KDQpXZSBhbHNvIGNvbXBhcmUgd2hldGhlciB5b3VuZyBsZWZ0LWZvb3RlZCBwbGF5ZXJzIGhhdmUgZ3JlYXRlciBhdmVyYWdlIHBvdGVudGlhbCB0aGFuIHRoZSByaWdodC1mb290ZWQuDQoNCiMjIyBEYXRhIHByZXByb2Nlc3NpbmcNCg0KT25seSBwbGF5ZXJzIGJvcm4gaW4gMjAwNCBhcmUgY29uc2lkZXJlZCB5b3VuZy4gVGhlcmVmb3JlIHdlIHJlZHVjZSB0aGUgZGF0YXNldCBhcyBmb2xsb3dzLg0KDQpgYGB7cn0NCg0KbGlicmFyeShkcGx5cikNCg0KIyBTdW1tYXJpemUgYXZlcmFnZSBwb3RlbnRpYWwgZm9yIGxlZnQtZm9vdGVkIHBsYXllcnMNCmxlZnRfZm9vdGVkX2F2ZyA8LSBmaWZhX2RmX3JlZHVjZWQgJT4lDQogIGZpbHRlcihwcmVmZXJyZWRfZm9vdCA9PSAnTGVmdCcgJiBmb3JtYXQoZG9iLCAiJVkiKSA9PSAiMjAwNCIpICU+JQ0KICBzdW1tYXJpc2UocGxheWVycyA9ICdMZWZ0LWZvb3RlZCcsIGF2ZyA9IG1lYW4ocG90ZW50aWFsLCBuYS5ybSA9IFRSVUUpKQ0KDQojIFN1bW1hcml6ZSBhdmVyYWdlIHBvdGVudGlhbCBmb3IgcmlnaHQtZm9vdGVkIHBsYXllcnMNCnJpZ2h0X2Zvb3RlZF9hdmcgPC0gZmlmYV9kZl9yZWR1Y2VkICU+JQ0KICBmaWx0ZXIocHJlZmVycmVkX2Zvb3QgPT0gJ1JpZ2h0JyAmIGZvcm1hdChkb2IsICIlWSIpID09ICIyMDA0IikgJT4lDQogIHN1bW1hcmlzZShwbGF5ZXJzID0gJ1JpZ2h0LWZvb3RlZCcsIGF2ZyA9IG1lYW4ocG90ZW50aWFsLCBuYS5ybSA9IFRSVUUpKQ0KDQojIENvbWJpbmUgYm90aCBzdW1tYXJpZXMNCmF2Z19wb3RlbnRpYWxfZGYgPC0gYmluZF9yb3dzKGxlZnRfZm9vdGVkX2F2ZywgcmlnaHRfZm9vdGVkX2F2ZykNCmF2Z19wb3RlbnRpYWxfZGYNCiAgIyBzZWxlY3Qoc2hvcnRfbmFtZSwgZG9iLCBwb3RlbnRpYWwsIGV2ZXJ5dGhpbmcoKSkNCmBgYA0KDQojIyMgUGxvdHRpbmcNCg0KRmluYWxseSwgd2UgdmlzdWFsaXplIHRoZSBtZWFucyBpbiBhIHNpbXBsZSBiYXIgcGxvdCBiZWxvdy4NCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQojIENyZWF0ZSBhIGJhciBwbG90IGNvbXBhcmluZyB0aGUgYXZlcmFnZSBwb3RlbnRpYWwgZm9yIGxlZnQgYW5kIHJpZ2h0LWZvb3RlZCBwbGF5ZXJzDQpnZ3Bsb3QoYXZnX3BvdGVudGlhbF9kZiwgYWVzKHggPSBwbGF5ZXJzLCB5ID0gYXZnLCBmaWxsID0gcGxheWVycykpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgbGFicyh0aXRsZSA9ICJDb21wYXJpc29uIG9mIEF2ZXJhZ2UgUG90ZW50aWFsIG9mIExlZnQtIGFuZCBSaWdodC1Gb290ZWQgUGxheWVycyIsDQogICAgICAgeCA9ICJGb290ZWRuZXNzIiwNCiAgDQogICAgICAgeSA9ICJBdmVyYWdlIFBvdGVudGlhbCIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygnIzMxNTNhMicsICJsaWdodGdyZXkiKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCmBgYA0KDQojIyBDb25jbHVzaW9uDQoNCldlIGh5cG90aGVzaXplZCB0aGF0IGxlZnQtZm9vdGVkIHBsYXllcnMgZ2VuZXJhbGx5IHBsYXkgaW4gbW9yZSBvZmZlbnNpdmUgcG9zaXRpb25zIHRoYXQgdGhlIHJpZ2h0LWZvb3RlZCBwbGF5ZXJzLiBBcyBvZiB0aGUgb2JzZXJ2YXRpb24gd2UgcGVyZm9ybWVkIGluIHRoaXMgZG9jdW1lbnQgd2UgY2FuIHJlamVjdCB0aGlzIGh5cG90aGVzaXMgc2luY2UgdGhlIGdyZWF0ZXN0IHByb3BvcnRpb24gb2YgbGVmdC1mb290ZWQgcGxheWVycyBhcmUgcGxheWluZyBpbiBkZWZlbnNpdmUgcG9zaXRpb25zLg0KDQpXZSBhbHNvIGh5cG90aGVzaXplZCB0aGF0IGxlZnQtZm9vdGVkIHBsYXllcnMgaGF2ZSBncmVhdGVyIG1hcmtldCB2YWx1ZSBhbmQgd2FnZSBvbiBhdmVyYWdlIHRoYW4gdGhlIHJpZ2h0LWZvb3RlZCBwbGF5ZXJzLiBCYXNlZCBvbiB0aGUgYW5hbHlzaXMsIHdlIGNhbiBkZWNsYXJlIHRoaXMgY2xhaW0gYXMgY29ycmVjdCBidXQgaXQgcmVtYWlucyBxdWVzdGlvbmFibGUgdG8gd2hhdCBleHRlbnQuDQoNCkZpbmFsbHkgd2Ugc2V0IGFub3RoZXIgaHlwb3RoZXNpcyB3aGljaCBzYXlzIHRoYXQgeW91bmcgbGVmdC1mb290ZWQgcGxheWVycyBoYXZlIGdyZWF0ZXIgcG90ZW50aWFsLiBBZnRlciByZXZpZXdpbmcgdGhlIGF2ZXJhZ2Ugd2UgY2FuIHByb2NsYWltIHRoaXMgZmluYWwgaHlwb3RoZXNpcyBhcyB0cnVlIGlmIHRoZSBvYnNlcnZlZCBkaWZmZXJlbmNlIGlzIHNpZ25pZmljYW50Lg0KDQojIyMgSHlwb3RoZXNpcyB0ZXN0aW5nDQoNCkZpcnN0IGh5cG90aGVzaXMgY2FuIGJlIHRlc3RlZCB2aWEgKipDaGktc3F1YXJlIHRlc3QqKiBmb3IgaW5kZXBlbmRlbmNlLiBUaGUgcmVzdCBvZiB0aGUgaHlwb3RoZXNlcyBtYXkgYmUgdGVzdGVkIGJ5IGEgc2ltcGxlICoqaW5kZXBlbmRlbnQgVHdvLXNhbXBsZSBULXRlc3QgKFN0dWRlbnQncyBULXRlc3QpKiogc2luY2Ugd2UgYXJlIGNvbXBhcmluZyB0aGUgbWVhbnMgb2YgaW5kZXBlbmRlbnQgZ3JvdXBzLg0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQoNCmZpZmFfZGZfY2xlYW4gPC0gZmlmYV9kZl9yZWR1Y2VkICU+JQ0KICBmaWx0ZXIoIWlzLm5hKHByZWZlcnJlZF9mb290KSAmICFpcy5uYShwb3NpdGlvbl9jYXRlZ29yeSkpDQoNCmNoaXNxLnRlc3QodGFibGUoZmlmYV9kZl9jbGVhbiRwcmVmZXJyZWRfZm9vdCwgZmlmYV9kZl9jbGVhbiRwb3NpdGlvbl9jYXRlZ29yeSkpDQoNCnQudGVzdCh2YWx1ZV9ldXIgfiBwcmVmZXJyZWRfZm9vdCwgZGF0YSA9IGZpZmFfZGZfY2xlYW4pDQp0LnRlc3Qod2FnZV9ldXIgfiBwcmVmZXJyZWRfZm9vdCwgZGF0YSA9IGZpZmFfZGZfY2xlYW4pDQp0LnRlc3QocG90ZW50aWFsIH4gcHJlZmVycmVkX2Zvb3QsIGRhdGEgPSBmaWZhX2RmX2NsZWFuKQ0KYGBgDQo=